package main;

import java.awt.BorderLayout;
import java.io.File;
import java.io.FileFilter;
import java.util.Vector;
import java.util.concurrent.TimeoutException;

import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JProgressBar;

import util.progressDialog;

public class MainFunctions {

	/**
	 * Function to backup apks and data.
	 * 
	 * @param out
	 *            Vector of {@link AppApk} configured with the backup options
	 * @param destDirectory
	 *            Local destiny directory to store the backup (without the last
	 *            ,and maybe, the first '/')
	 */
	void backupApkData(Vector<AppApk> out, String destDirectory,
			String deviceSerial) {
		AdbCommands adbCmd;
		try {
			adbCmd = new AdbCommands(deviceSerial);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return;
		}
		if (out.size() <= 0) {
			return;
		}
		progressDialog jProgrresDialog = new progressDialog("Progres",
				out.size());
		jProgrresDialog.start();
		for (int i = 0; i < out.size(); i++) {
			jProgrresDialog.setProgressDialoj(i);
			if (out.get(i).isSelected()) {
				String from = out.get(i).getPathApk() + out.get(i).getNameApk();
				String to = destDirectory + out.get(i).getPathApk()
						+ out.get(i).getNameApk();
				if (out.get(i).isInSD()) {
					// TODO rename the apk to store with the other apks
					to = destDirectory + "/data/app/"
							+ out.get(i).getPackageName() + ".apk";
				}
				long timeOut = 10000;
				if (!adbCmd.pullFile(from, to, timeOut)) {
					out.get(i).setBackupError(true);
					out.get(i).setSelected(true);
				} else {
					out.get(i).setSelected(false);
				}
				if (out.get(i).isData()) {
					timeOut = 60000;
					if (adbCmd.fileExist("/data/data/", out.get(i)
							.getPackageDataPath())) {
						if (!adbCmd.pullFile("/data/data/"
								+ out.get(i).getPackageDataPath(),
								destDirectory + "/data/data/"
										+ out.get(i).getPackageDataPath(),
								timeOut)) {
							out.get(i).setBackupError(true);
							out.get(i).setSelected(true);
							out.get(i).setData(true);
						} else {
							out.get(i).setData(false);
						}
					} else {
						out.get(i).setData(false);
					}
				}
				System.out.println(out.get(i));
			}
			try {
				Thread.sleep(0);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	/**
	 * Function to backup (copy) system data, like Wifi, sms, ...
	 * 
	 * @param dataPath
	 *            Vector of strings with the path to backup
	 * @param destDirectory
	 *            Local destiny directory to store the backup (without the last
	 *            ,and maybe, the first '/')
	 */
	void backupSysData(Vector<String> dataPath, String destDirectory,
			String deviceSerial) {
		AdbCommands adbCmd;
		try {
			adbCmd = new AdbCommands(deviceSerial);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return;
		}
		for (int i = 0; i < dataPath.size(); i++) {
			long timeOut = 60000;
			adbCmd.pullFile(dataPath.get(i), destDirectory + dataPath.get(i),
					timeOut);
			System.out.println(dataPath.get(i));
		}
	}

	/**
	 * Function to install the apks. (you can not install system apps! you need
	 * to copy to /system/app and reboot)
	 * 
	 * @param out
	 *            vector of {@link AppApk} with the configuration (pathApk and
	 *            nameApk, at least)
	 * @param sourceDirectory
	 *            the root folder of the backup
	 * @param keepData
	 *            {@link Boolean}, <code>true</code> to keep data of the app
	 */
	void installApk(Vector<AppApk> out, String sourceDirectory,
			boolean keepData, String deviceSerial) {
		AdbCommands adbCmd;
		try {
			adbCmd = new AdbCommands(deviceSerial);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return;
		}
		for (int i = 0; i < out.size(); i++) {
			if (out.get(i).isSelected() && !out.get(i).isSystenApp()) {
				String fromDirectory = sourceDirectory
						+ out.get(i).getPathApk();

				switch ((new identifyOS().identifyOS())) {
				default: // Getout the first "/"

					// toDirectory = out.get(i).getPathApk().substring(1);
					break;
				}

				long timeOut = 10000;
				adbCmd.installApk(fromDirectory, out.get(i).getNameApk(),
						keepData, out.get(i).isInSD(), timeOut);
				System.out.println(out.get(i));
			}
		}
	}

	/**
	 * Function to restore /data/data/
	 * 
	 * @param out
	 *            vector of {@link AppApk} with the configuration
	 *            (PackageDataPath and isData, at least)
	 * @param sourceDirectory
	 *            the root folder of the backup
	 */
	void restoreDataData(Vector<AppApk> out, String sourcetDirectory,
			String deviceSerial) {
		AdbCommands adbCmd;
		try {
			adbCmd = new AdbCommands(deviceSerial);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return;
		}
		for (int i = 0; i < out.size(); i++) {
			if (out.get(i).isSelected()) {
				String toDirectory = "/data/data/"
						+ out.get(i).getPackageDataPath();

				switch ((new identifyOS().identifyOS())) {
				default: // Getout the first "/"

					// toDirectory = out.get(i).getPathApk().substring(1);
					break;
				}

				long timeOut = 10000;
				if (out.get(i).isData()) {
					timeOut = 60000;
					adbCmd.pushFile(
							sourcetDirectory + "/data/data/"
									+ out.get(i).getPackageDataPath(),
							toDirectory, timeOut);
				}
				System.out.println(out.get(i));
			}
		}
	}

	/**
	 * Function to rename the apks from a directory.
	 * 
	 * @param outDirectory
	 *            The directory with the apks
	 */
	void renameApk(String outDirectory, String deviceSerial) {
		File dir = new File(outDirectory);
		String[] fileList = dir.list();
		for (int i = 0; i < fileList.length; i++) {
			if (fileList[i].endsWith(".apk")) {
				String inName = outDirectory + fileList[i];
				System.out.println(inName);
				AdbCommands adbCmd;
				try {
					adbCmd = new AdbCommands(deviceSerial);
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					return;
				}
				Vector<String> out = new Vector<String>();
				adbCmd.getApkInformation(inName, out);

				String temp = findNameLabel(out);
				if (temp != null) {
					String outName = outDirectory + temp;
					System.out.println(outName);
					temp = findVersionName(out);
					outName = outName + "_" + temp + ".apk";
					System.out.println(outName);
					System.out.println(outName);
					// File (or directory) with old name
					File file = new File(inName);

					// File (or directory) with new name
					File file2 = new File(outName);

					// Rename file (or directory)
					boolean success = file.renameTo(file2);
				}
			}
		}
	}

	private String findLabel(Vector<String> out, String label) {
		Vector<String> temp = out;
		int i = 0;
		while ((temp.size() > i) && (temp.get(i).indexOf(label) < 0)) {
			i++;
		}
		if (temp.size() <= i) {
			return null;
		}
		int firstIndex = temp.get(i).indexOf(label) + label.length();
		int lastIndex = temp.get(i).indexOf("'", firstIndex);
		return out.get(i).substring(firstIndex, lastIndex);
	}

	/**
	 * Function to get the apk's application-label
	 * 
	 * @param out
	 *            The output of the funcion getNameApk
	 * @return The name of the application
	 */
	private String findNameLabel(Vector<String> out) {
		Vector<String> temp = out;
		int i = 0;
		while ((temp.size() > i)
				&& (temp.get(i).indexOf("application-label:") < 0)) {
			i++;
		}
		if (temp.size() <= i) {
			return null;
		}
		int firstIndex = temp.get(i).indexOf(':') + 2;
		int lastIndex = temp.get(i).length() - 1;
		return out.get(i).substring(firstIndex, lastIndex);
	}

	/**
	 * Function to get the apk's version
	 * 
	 * @param out
	 *            The output of the funcion getNameApk
	 * @return The version of the application
	 */
	private String findVersionName(Vector<String> out) {
		Vector<String> temp = out;
		int i = 0;
		while ((temp.size() > i) && (temp.get(i).indexOf("versionName=") < 0)) {
			i++;
		}
		if (temp.size() <= i) {
			return "";
		}
		int firstIndex = temp.get(i).indexOf("versionName=")
				+ "versionName=".length() + 1;
		int lastIndex = temp.get(i).length() - 1;
		return out.get(i).substring(firstIndex, lastIndex);
	}

	Vector<String> listFolders(String directory) {
		Vector<String> folderList = new Vector<String>();
		File root = new File(directory);
		File[] dirs = root.listFiles(directoryFilter);
		for (File f : dirs) {
			System.out.println(f.getName());
			folderList.add(f.getName());
		}
		return folderList;
	}

	private FileFilter directoryFilter = new FileFilter() {
		public boolean accept(File file) {
			// if the file extension is .txt return true, else false
			if (file.isDirectory()) {
				return true;
			}
			return false;
		}
	};

	Vector<AppApk> listFolderApks(String rootFolder) {
		// TODO Read apks from data/app and system/app
		Vector<AppApk> vectorApk = new Vector<AppApk>();
		String userAppFolder = "/data/app/";
		String sysAppFolder = "/system/app/";
		// /////////////////////
		File dir = new File(rootFolder + userAppFolder);
		String[] fileList = dir.list();
		for (int i = 0; i < fileList.length; i++) {
			if (fileList[i].endsWith(".apk")) {
				String inName = rootFolder + userAppFolder + fileList[i];
				System.out.println(inName);
				AdbCommands adbCmd;
				try {
					adbCmd = new AdbCommands(null);
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					return vectorApk;
				}
				Vector<String> out = new Vector<String>();
				String apk = fileList[i];
				String appPackage = "";
				String name = "";
				int firstIndex = 0;
				int lastIndex = apk.indexOf('-');
				if (lastIndex < 0) {
					lastIndex = apk.indexOf('.');
				}
				appPackage = apk.substring(firstIndex, lastIndex);
				name = appPackage;

				if (adbCmd.getApkInformation(inName, out)) {
					appPackage = findLabel(out, "package: name='");
					name = findNameLabel(out);
				}

				// TODO get the necesary information to AppApk
				AppApk mAppApk = new AppApk("/data/app", appPackage, apk);
				mAppApk.setName(name);
				vectorApk.add(mAppApk);
			}
		}
		// /////////////////////
		return vectorApk;
	}
}
